package com.szh.edu.student.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.szh.common.result.Result;
import com.szh.edu.student.client.TeacherFeignClient;
import com.szh.edu.student.mapper.StudentMapper;
import com.szh.edu.student.service.StudentService;
import com.szh.common.enums.ResultCodeEnum;
import com.szh.common.enums.SexEnum;
import com.szh.common.exception.ServiceEduException;
import com.szh.model.Student;
import com.szh.model.Teacher;
import com.szh.vo.StudentQueryVo;
import com.szh.vo.StudentSaveVo;
import com.szh.vo.StudentUpdateVo;
import com.szh.vo.TeacherQueryVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: SongZiHao
 * @date: 2023/5/6
 */
@Service
public class StudentServiceImpl implements StudentService {

    private static final Logger LOGGER = LoggerFactory.getLogger(StudentServiceImpl.class);

    @Resource
    private StudentMapper studentMapper;

    @Resource
    private TeacherFeignClient teacherFeignClient;

    /**
     * 根据id查询学生
     * @param id 学生id
     * @return Student
     */
    @Override
    public Student findStudentById(Long id) {
        LOGGER.info("findStudentById start....");
        LOGGER.info("待查询学生id ===> {}", id);
        Student student = studentMapper.findStudentById(id);
        if (null == student) {
            LOGGER.error("根据此 id ===> {} 查询的学生信息为空....", id);
            throw new ServiceEduException(ResultCodeEnum.QUERY_ONE_NOT_FOUND.getCode(),
                    ResultCodeEnum.QUERY_ONE_NOT_FOUND.getMessage());
        }
        LOGGER.info("根据此 id ===> {} 查询的学生信息 ===> {}", id, JSON.toJSONString(student));
        return student;
    }

    /**
     * 查询所有学生
     * @return List<Student> 学生列表
     */
    @Override
    public List<Student> findAllStudents() {
        LOGGER.info("findAllStudents start....");
        return studentMapper.findAllStudents();
    }

    /**
     * 条件查询学生，带分页
     * @param page 页码
     * @param limit 每页记录数
     * @param studentQueryVo 查询条件
     * @return Map<String, Object>
     */
    @Override
    public Map<String, Object> findStudentsByConditionPage(Long page, Long limit, StudentQueryVo studentQueryVo) {
        LOGGER.info("findStudentsByConditionPage start....");
        int pageNum = page == 0L ? 1 : page.intValue();
        int pageSize = limit == 0L ? 10 : limit.intValue();
        LOGGER.info("findStudentsByConditionPage接口入参 ===> page页码：{}", pageNum);
        LOGGER.info("findStudentsByConditionPage接口入参 ===> limit每页记录数：{}", pageSize);
        LOGGER.info("findStudentsByConditionPage接口入参 ===> 查询条件：{}", studentQueryVo);
        PageHelper.startPage(pageNum, pageSize);
        List<Student> studentList = studentMapper.findStudentsByConditionPage(studentQueryVo);
        if (CollectionUtils.isEmpty(studentList)) {
            LOGGER.error("根据此条件查询的学生列表为空 ===> {}", studentQueryVo);
            return new HashMap<>();
        }
        PageInfo<Student> pageInfo = new PageInfo<>(studentList);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("total", pageInfo.getTotal());
        resultMap.put("rows", pageInfo.getList());
        LOGGER.info("根据此条件查询的学生列表 ===> {}", JSON.toJSONString(resultMap));
        return resultMap;
    }

    /**
     * 新增学生
     * @param studentSaveVo 学生新增vo类
     * @return 是否新增成功
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,
                   isolation = Isolation.REPEATABLE_READ,
                   rollbackFor = Exception.class)
    public boolean saveStudent(StudentSaveVo studentSaveVo) {
        LOGGER.info("saveStudent start....");
        LOGGER.info("新增学生的部分信息 ===> {}", JSON.toJSONString(studentSaveVo));
        String name = studentSaveVo.getName();
        Integer age = studentSaveVo.getAge();
        String hobby = studentSaveVo.getHobby();
        String address = studentSaveVo.getAddress();
        if (StringUtils.isEmpty(name) || StringUtils.isEmpty(hobby) ||
            age <= 0 || StringUtils.isEmpty(address)) {
            LOGGER.error("新增学生的信息中存在非法数据 ===> {}", JSON.toJSONString(studentSaveVo));
            throw new ServiceEduException(ResultCodeEnum.ILLEGAL_PARAM.getCode(),
                    ResultCodeEnum.ILLEGAL_PARAM.getMessage());
        }
        List<Student> studentList = studentMapper.findAllStudents();
        List<String> nameList = studentList.stream().map(Student::getName).collect(Collectors.toList());
        //也可能存在重名重姓，此处判断纯属娱乐
        if (nameList.contains(name)) {
            LOGGER.error("此 name ===> {} 已存在于数据库中，请修改姓名之后再次尝试插入!", name);
            throw new ServiceEduException(ResultCodeEnum.RECORD_ALREADY_EXISTS.getCode(),
                    ResultCodeEnum.RECORD_ALREADY_EXISTS.getMessage());
        }
        Student student = Student.builder()
                .name(name)
                .age(age)
                .sex(studentSaveVo.getSex() == 1 ? SexEnum.MAN.getSexId() : SexEnum.WOMAN.getSexId())
                .intro(Objects.isNull(studentSaveVo.getIntro()) ? "" : studentSaveVo.getIntro())
                .hobby(hobby)
                .address(address).build();
        student.setCreateTime(new Date());
        LOGGER.info("待新增学生的信息 ===> {}", JSON.toJSONString(student));
        int row = studentMapper.insertStudent(student);
        if (row == 0) {
            LOGGER.error("新增异常....");
            throw new ServiceEduException(ResultCodeEnum.INSERT_FAILED.getCode(),
                    ResultCodeEnum.INSERT_FAILED.getMessage());
        } else {
            LOGGER.info("新增成功 ===> {}", JSON.toJSONString(student));
            return true;
        }
    }

    /**
     * 根据id修改学生
     * @param studentUpdateVo 学生修改vo类
     * @return 是否修改成功
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,
                   isolation = Isolation.REPEATABLE_READ,
                   rollbackFor = Exception.class)
    public boolean updateStudent(StudentUpdateVo studentUpdateVo) {
        LOGGER.info("updateStudent start....");
        LOGGER.info("待修改学生的部分信息 ===> {}", JSON.toJSONString(studentUpdateVo));
        Long id = studentUpdateVo.getId();
        Student modStudent = studentMapper.findStudentById(id);
        if (null == modStudent) {
            LOGGER.error("待修改的学生记录不存在，id ===> {}", id);
            throw new ServiceEduException(ResultCodeEnum.QUERY_ONE_NOT_FOUND.getCode(),
                    ResultCodeEnum.QUERY_ONE_NOT_FOUND.getMessage());
        }
        Student student = new Student();
        BeanUtils.copyProperties(studentUpdateVo, student);
        if (StringUtils.isEmpty(student.getName()) || StringUtils.isEmpty(student.getHobby()) ||
            student.getAge() <= 0 || StringUtils.isEmpty(student.getAddress())) {
            LOGGER.error("修改之后的学生部分信息不合法，请更正一下再次提交 ===> {}", JSON.toJSONString(student));
            throw new ServiceEduException(ResultCodeEnum.ILLEGAL_PARAM.getCode(),
                    ResultCodeEnum.ILLEGAL_PARAM.getMessage());
        }
        int row = studentMapper.updateStudent(student);
        if (row == 0) {
            LOGGER.error("修改异常....");
            throw new ServiceEduException(ResultCodeEnum.UPDATE_FAILED.getCode(),
                    ResultCodeEnum.UPDATE_FAILED.getMessage());
        } else {
            LOGGER.info("修改成功!!!");
            return true;
        }
    }

    /**
     * 根据id逻辑删除学生
     * @param id 待删学生id
     * @return 是否删除成功
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,
                   isolation = Isolation.REPEATABLE_READ,
                   rollbackFor = Exception.class)
    public boolean deleteStudentById(Long id) {
        LOGGER.info("deleteStudentById start....");
        LOGGER.info("待删除学生id ===> {}", id);
        Student delStudent = studentMapper.findStudentById(id);
        if (null == delStudent) {
            LOGGER.error("待删除学生记录不存在，id ===> {}", id);
            throw new ServiceEduException(ResultCodeEnum.QUERY_ONE_NOT_FOUND.getCode(),
                    ResultCodeEnum.QUERY_ONE_NOT_FOUND.getMessage());
        }
        int row = studentMapper.deleteStudentById(id);
        if (row == 0) {
            LOGGER.error("根据此 id ===> {} 删除学生失败", id);
            throw new ServiceEduException(ResultCodeEnum.DELETE_FAILED.getCode(),
                    ResultCodeEnum.DELETE_FAILED.getMessage());
        } else {
            LOGGER.info("根据此 id ===> {} 删除学生成功，学生信息 ===> {}", id, JSON.toJSONString(delStudent));
            return true;
        }
    }

    /**
     * 批量删除学生
     * @param studentIds 待删学生id集合
     * @return 是否批量删除成功
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,
                   isolation = Isolation.REPEATABLE_READ,
                   rollbackFor = Exception.class)
    public boolean deleteBatchByIds(List<Long> studentIds) {
        LOGGER.info("deleteBatchByIds start....");
        LOGGER.info("待删学生id集合 ===> {}", JSON.toJSONString(studentIds));
        int row = studentMapper.deleteBatchByIds(studentIds);
        if (row == studentIds.size()) {
            LOGGER.info("批量删除成功!!!");
            return true;
        } else {
            LOGGER.error("批量删除异常....");
            throw new ServiceEduException(ResultCodeEnum.DELETE_FAILED.getCode(),
                    ResultCodeEnum.DELETE_FAILED.getMessage());
        }
    }

    /**
     * 远程接口调用：根据id查询教师
     * @param id 教师id
     * @return Teacher
     */
    @Override
    public Teacher openFeignSelectTeacherById(Long id) {
        LOGGER.info("openFeignSelectTeacherById start....");
        LOGGER.info("待查询教师id ===> {}", id);
        Result<Teacher> result = teacherFeignClient.selectTeacherById(id);
        Teacher teacher = result.getData();
        if (null == teacher) {
            LOGGER.error("根据此 id ===> {} 远程查询的教师信息为空....", id);
            throw new ServiceEduException(ResultCodeEnum.QUERY_ONE_NOT_FOUND.getCode(),
                    ResultCodeEnum.QUERY_ONE_NOT_FOUND.getMessage());
        }
        LOGGER.info("根据此 id ===> {} 远程查询的教师信息 ===> {}", id, JSON.toJSONString(teacher));
        return teacher;
    }

    /**
     * 远程接口调用：查询所有教师
     * @return List<Teacher> 教师列表
     */
    @Override
    public List<Teacher> openFeignSelectAll() {
        LOGGER.info("openFeignSelectAll start....");
        Result<List<Teacher>> result = teacherFeignClient.selectAll();
        List<Teacher> teacherList = result.getData();
        LOGGER.info("远程查询到的教师列表 ===> {}", JSON.toJSONString(teacherList));
        return teacherList;
    }

    /**
     * 远程接口调用：条件查询教师，带分页
     * @param page 页码
     * @param limit 每页记录数
     * @param teacherQueryVo 查询条件
     * @return Map<String, Object>
     */
    @Override
    public Map<String, Object> openFeignSelectTeachersByConditionPage(Long page, Long limit, TeacherQueryVo teacherQueryVo) {
        LOGGER.info("openFeignSelectTeachersByConditionPage start....");
        Result<Map<String, Object>> result = teacherFeignClient.selectTeachersByConditionPage(page, limit, teacherQueryVo);
        Map<String, Object> map = result.getData();
        List<Teacher> records = (List<Teacher>) map.get("records");
        if (CollectionUtils.isEmpty(records)) {
            LOGGER.error("根据此条件远程查询的教师列表为空 ===> {}", JSON.toJSONString(teacherQueryVo));
            return new HashMap<>();
        }
        LOGGER.info("根据此条件远程查询的教师总数 ===> {}", map.get("total"));
        LOGGER.info("根据此条件远程查询的教师列表 ===> {}", JSON.toJSONString(records));
        return map;
    }
}


// cst时间转换成gmt时间，工具代码
//        SimpleDateFormat gmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        SimpleDateFormat cst = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);
//        Date dateTimeBegin = null;
//        Date dateTimeEnd = null;
//        try {
//            dateTimeBegin = cst.parse(studentQueryVo.getCreateTimeBegin());
//            dateTimeEnd = cst.parse(studentQueryVo.getCreateTimeEnd());
//        } catch (ParseException e) {
//            e.printStackTrace();
//        }
//        String dateStringBegin = gmt.format(dateTimeBegin);
//        String dateStringEnd = gmt.format(dateTimeEnd);
//        studentQueryVo.setCreateTimeBegin(dateStringBegin);
//        studentQueryVo.setCreateTimeEnd(dateStringEnd);
